import React from 'react';
import {Route} from 'react-router-dom';
import {Tool, ToolHistory} from './index';
import {configRouter, configLayout} from '../router/Config';

/**
 * 路由管理工具类
 */
export default {
  /**
   * 格式化路由
   * 注意：当用户角色类型改变时，需要重新调用该方法
   * @param auth 当前用户的角色类型。如果auth为空，则不校验权限。
   * @param lvMax 左侧菜单的最大层级。默认值：2
   */
  formatRouter(auth, lvMax = 2) {
    let routerMenu = {}; //左侧菜单的路由列表
    let routerFormat = {}; //格式化的路由列表

    Object.keys(configRouter).forEach((key) => {
      let item = configRouter[key];
      let dataLayout = configLayout[key];
      if (!item || item.length == 0) return;

      routerMenu[key] = routerMenu[key] || [];
      routerFormat[key] = routerFormat[key] || {};
      item.forEach((item2, index) => {
        let {label, path, auths, children, ...other} = item2;
        if (auth && auths && !auths.includes(auth)) return;

        //如果父级路由为'/'，则不拼接父级路由
        path = `${dataLayout.path === '/' ? '' : dataLayout.path}${path.startsWith('/') ? '' : '/'}${path}`;
        let data = {index, label, path, ...other};
        routerMenu[key].push(data);
        routerFormat[key][path] = data;

        //当前的菜单层级列表
        data.routes = [{label, path}];
        //指定菜单项的key
        if (children && children.length > 0) {
          data.keyGroup = path;
          data.children = [];
          this.formatRouterRecursion(routerFormat[key], data, children, auth, lvMax);
        } else {
          data.keyItem = path;
        }
      });
    });
    return {routerMenu, routerFormat};
  },

  /**
   * 格式化路由：递归遍历
   * @param route 格式化的路由信息
   * @param data 上级路由
   * @param list 子路由列表
   * @param auth 当前用户的角色类型
   * @param lvMax 左侧菜单的最大层级
   * @param lv 左侧菜单的当前层级。默认值：2
   */
  formatRouterRecursion(route, data, list, auth, lvMax, lv = 2) {
    if (!list || list.length == 0) return;

    list.forEach((item, index) => {
      let {label, path, auths, children, ...other} = item;
      if (auth && auths && !auths.includes(auth)) return;

      path = `${data.path}${path.startsWith('/') ? '' : '/'}${path}`;
      let data2 = {index, label, path, ...other};
      data2.routes = [...data.routes, {label, path}];
      if (lv <= lvMax) {
        data2.keyGroup = data.keyGroup;
        data2.keyItem = path;
        data.children.push(data2);
      } else {
        data2.keyGroup = data.keyGroup;
        data2.keyItem = data.keyItem;
      }
      route[path] = data2;
      this.formatRouterRecursion(route, data2, children, auth, lvMax, lv + 1);
    });
  },

  /**
   * 生成路由页面列表
   */
  routes() {
    let result = [];
    let list = this.formatRouter().routerFormat;
    this.key = 0; //重置路由组件的key

    Object.keys(list).forEach((type) => {
      let item = list[type];
      let {path, view} = configLayout[type];
      let routes = [];
      Object.keys(item).forEach((key2) => {
        let item2 = item[key2];
        if (item2.view) routes.push(this.route(item2.path, item2.view));
      });
      result.push(this.route(path, view, false, {type, routes}));
    });

    return result;
  },

  /**
   * 生成懒加载的路由页面
   * 当view为组件名时，使用模板字符串传入二级路径的变量，实现懒加载.注意：webpack解析时，一级路径需要使用别名。
   * 注意：如果在路由组件外部，import了该组件，那么懒加载就会失效。因为import是编译时加载。
   * @param path  url的路径
   * @param View  组件或组件名。如果是组件名，则为src目录下的相对路径。
   * @param exact 表示相同path的Route只会渲染第一个，这里设置默认true。注意：使用嵌套路由时，外出路由的exact必须为false。
   * @param props 组件属性
   */
  route(path, View, exact = true, props) {
    let component;
    if (typeof View === 'string') {
      component = this.lazyLoad(() => import(`@/${View}`), props); //生成懒加载的页面
    } else {
      component = props ? () => <View {...props} /> : View;
    }

    this.key = this.key || 0;
    return <Route key={this.key++} path={path} view={View} component={component} exact={exact} />;
  },

  /**
   * 路由懒加载
   * @param view 通过import函数得到的组件
   * @param props 组件属性
   */
  lazyLoad(view, props = {}) {
    //懒加载组件
    class AsyncComponent extends React.Component {
      constructor(props) {
        super(props);
        this.state = {component: null};
      }
      componentDidMount() {
        view().then((mod) => {
          this.setState({component: mod.default || mod});
        });
      }
      render() {
        const C = this.state.component;
        return C ? <C {...this.props} {...props} /> : null;
      }
    }
    return AsyncComponent;
  },
  /**
   * 检查是否登录
   */
  checkLogin() {
    //如果没有登录，则跳转登录页面
    if (!Tool.getUser().token) {
      ToolHistory.href('/home/login');
      return false;
    }
    return true;
  },

  /**
   * 检查路由访问权限
   * @param routerFormat 格式化的路由列表
   */
  checkRoute(routerFormat) {
    let path = ToolHistory.getRoutePath(); //当前页面的路由地址
    let result;
    Object.keys(routerFormat).some((key) => {
      let pathLayout = `/${key}`; //Layout组件的路由
      if (path === pathLayout) {
        result = {keyGroup: path}; //keyGroup用于展开Layout的左侧菜单
      } else {
        let item = routerFormat[key];
        result = item[path];
      }
      return result;
    });

    //如果没有访问权限，则跳转403页面
    if (!result) ToolHistory.href('/403');
    return result;
  }
};
